/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.lcm.metadata.core.entity;

import com.inspur.edp.lcm.metadata.api.entity.ProjectHeader;
import com.inspur.edp.lcm.metadata.api.mvnEntity.MavenPackageRefs;
import com.inspur.edp.lcm.metadata.core.manager.VersionManager;
import lombok.NonNull;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 元数据包依赖索引
 * 在MetadataPackageForIndex索引类基础上,增加了子节点 以及依赖Maven\Package缓存
 *
 * @author sunhongfei01
 * @date 2021-8-25
 */
@Slf4j
@Setter
public class MdProjectDependencyNode {
    // 记录依赖元数据包名列表
    private Set<String> metadataPackageRefs;

    // 记录元数据包包 Maven依赖GAV列表
    private List<MavenPackageRefs> mavenRefs;
    // 记录元数据包 Package依赖包名列表
    // private List<String> packageRepoKeys = new ArrayList<>();
    // 记录元数据工程的BO内依赖列表
    private List<ProjectHeader> projectRefs;
    // 记录元数据工程的数据库依赖列表
    private Set<String> mdpkgRefs;
    //记录元数据工程的IDP元数据引用
    private Set<String> idpMetadataIds;

    private String metadataPackageName;

    private String location;

    private String depFileLocation;

    private List<String> metadataIds;

    private MdProjDependencySource sourceName;

    private String sourceVersion;

    private long lastModified;

    public String getMetadataPackageName() {
        return metadataPackageName;
    }

    public void setMetadataPackageName(String metadataPackageName) {
        this.metadataPackageName = metadataPackageName;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getDepFileLocation() {
        return depFileLocation;
    }

    public void setDepFileLocation(String depFileLocation) {
        this.depFileLocation = depFileLocation;
    }

    public List<String> getMetadataIds() {
        return metadataIds;
    }

    public void setMetadataIds(List<String> metadataIds) {
        this.metadataIds = metadataIds;
    }

    public MdProjDependencySource getSourceName() {
        return sourceName;
    }

    public void setSourceName(MdProjDependencySource sourceName) {
        this.sourceName = sourceName;
    }

    public String getSourceVersion() {
        return sourceVersion;
    }

    public void setSourceVersion(String sourceVersion) {
        this.sourceVersion = sourceVersion;
    }

    public long getLastModified() {
        return lastModified;
    }

    public void setLastModified(long lastModified) {
        this.lastModified = lastModified;
    }

    @NonNull
    public Set<String> getMetadataPackageRefs() {
        return metadataPackageRefs == null ? metadataPackageRefs = new HashSet<>() : metadataPackageRefs;
    }

    @NonNull
    public List<MavenPackageRefs> getMavenRefs() {
        return mavenRefs == null ? mavenRefs = new ArrayList<>() : mavenRefs;
    }

    @NonNull
    public List<ProjectHeader> getProjectRefs() {
        return projectRefs == null ? projectRefs = new ArrayList<>() : projectRefs;
    }

    @NonNull
    public Set<String> getMdpkgRefs() {
        return mdpkgRefs == null ? mdpkgRefs = new HashSet<>() : mdpkgRefs;
    }


    @NonNull
    public Set<String> getIdpMetadataIds() {
        return idpMetadataIds == null ? idpMetadataIds = new HashSet<>() : idpMetadataIds;
    }

    /**
     * 判断当前节点是否bo间引用
     *
     * @return 是否bo类型节点
     */
    public boolean isBO() {
        return this.sourceName == MdProjDependencySource.BO;
    }

    /**
     * 判断两节点的更新时间是否相同
     * 用于对比文件与缓存,判断是否需要更新缓存
     *
     * @param otherNode 对比节点
     * @return 是否 时间不一致
     */
    public boolean checkIsChanged(MdProjectDependencyNode otherNode) {
        return this.lastModified != otherNode.getLastModified();
    }

    /**
     * 判断两依赖节点是否相同(仅对比部分属性)
     *
     * @param targetNode 对比依赖节点
     * @return 是否相同
     */
    public boolean equals(MdProjectDependencyNode targetNode) {
        if (targetNode == null) {
            return false;
        }
        return StringUtils.equals(this.location, targetNode.getLocation())
                && StringUtils.equals(this.metadataPackageName, targetNode.getMetadataPackageName())
                && this.sourceName == targetNode.getSourceName()
                && !checkIsChanged(targetNode);
    }

    /**
     * 与目标依赖节点 的版本对比, 判断当前节点是否更新
     * 1. 先对比来源, 按照 BO(不应存在) > 数据库 > Maven > Package
     * @param targetNode 目标依赖节点
     * @param isEqual    版本相等时 是否认为更新
     * @return 当前依赖节点版本 是否  大于(isEqual=false)/ 大于等于 (isEqual=true) 目标依赖节点版本
     */
    public boolean isVersionNewerThan(MdProjectDependencyNode targetNode, boolean isEqual) {
        // 比较版本前先比较来源
        // TODO
        if (this.sourceName != targetNode.getSourceName()) {
            // 返回枚举类对比结果, 枚举类中排序为当前优先级顺序
            return this.sourceName.compareTo(targetNode.getSourceName()) < 0;
        }
        // 若为同一来源,则比较版本
        if (StringUtils.equals(this.sourceVersion, targetNode.getSourceVersion())) {
            return isEqual;
        }

        String versionResult = VersionManager.versionCompare(this.sourceVersion, targetNode.getSourceVersion());
        return StringUtils.equals(versionResult, this.sourceVersion);
    }
}
